#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>

#define RANGE(x, y, z) if(x >= y && x <= z)
#define CASE_RET(x, y) case x: return y

typedef uint64_t ull;

enum
{
    MODE_DEC = 0,
    MODE_HEX,
    MODE_BIN,
    MODE_STR,
    MODE_PAD
};

static const char *mode_prefix[] = {
    "",
    "0x",
    "0b"
};

ull hex2digit(const char *str)
{
    int n = 1;
    ull res = 0;
    for(int i = strlen(str) - 1; i >= 0; i--)
    {
        int t;
        RANGE(str[i], 'a', 'f')
            t = str[i] - 'a' + 10;
        else RANGE(str[i], 'A', 'F')
            t = str[i] - 'A' + 10;
        else RANGE(str[i], '0', '9')
            t = str[i] - '0';
        else
            continue;
#ifdef DEBUG
printf("%c: %d\n", str[i], t);
#endif
        res += t * n;
        n *= 16;
    }
    return res;
}

ull bin2digit(const char *str)
{
    int n = 1;
    ull res = 0;
    for(int i = strlen(str) - 1; i >= 0; i--)
    {
        int t;
        RANGE(str[i], '0', '1')
            t = str[i] - '0';
        else
            continue;

#ifdef DEBUG
printf("%c: %d\n", str[i], t);
#endif
        res += t * n;
        n *= 2;
    }
    return res;
}

const char *digit2str(int radix, ull num, int need_padding)
{
    int buf_pos;
    int is_zero;
    static char buf[128] = {};

    if((is_zero = !num) && !need_padding)
        return "0";

    if(radix < 2 || radix > 36)
        return NULL;

    buf_pos = sizeof(buf) - 2;
    while(num && buf_pos >= 0)
    {
        int t = num % radix;
        buf[buf_pos] = t < 10 ? '0' + t : 'A' + (t - 10);
        num /= radix;
        buf_pos--;
    }

    if(need_padding)
    {
        int padding = 0;
        for(int i = 0xFF; i; i /= radix) padding++;

#ifdef DEBUG
printf("%lu: %lu %d\n", sizeof(buf) - 2 - buf_pos, is_zero * padding ?: (padding - ((sizeof(buf) - 2 - buf_pos) % padding)) % padding, padding);
#endif
        int cur_len = sizeof(buf) - 2 - buf_pos;
        for(int i = is_zero * padding ?: (padding - (cur_len % padding)) % padding; i > 0; i--)
        {
            buf[buf_pos] = '0';
            buf_pos--;
        }
    }

    buf_pos++;

    return (const char*)buf + buf_pos;
}

void print_str_digit(const char *str, int radix)
{
    printf("Str(\"%s\"):\n", str);

    size_t str_len = strlen(str);
    for(size_t i = 0; i < str_len; i++)
    {
        printf("  \'%c\': %s\n", str[i], digit2str(radix, str[i], 1));
    }
    return;
}

int parse_mode(const char mode)
{
    switch(mode)
    {
        CASE_RET('d', MODE_DEC);
        CASE_RET('h', MODE_HEX);
        CASE_RET('b', MODE_BIN);
        CASE_RET('s', MODE_STR);
        CASE_RET('p', MODE_PAD);
    }
    return 0;
}

int main(int argc, const char **argv)
{
    if(argc < 3) return 0;

    int mode = 0;
    int radix = 0;
    int need_padding = 0;
    for(int i = 1; i < argc; i++)
    {
#ifdef DEBUG
printf("argv[%d]: %s\n", i, argv[i]);
#endif
        if(strlen(argv[i]) == 2 && argv[i][0] == '/')
        {
            int t = parse_mode(argv[i][1]);

            if(t == MODE_PAD)
                need_padding = !need_padding;
            else
                mode = t;

            continue;
        }

        if(!radix)
        {
            radix = atoi(argv[i]);
        }
        else
        {
            ull n;

            if(mode == MODE_STR)
            {
                print_str_digit(argv[i], radix);
            }
            else
            {
                n = mode ? ((mode == 1) ? hex2digit(argv[i]) : bin2digit(argv[i]))
                             : atoll(argv[i]);
                printf("%s%s: %s\n", mode_prefix[mode], argv[i], digit2str(radix, n, need_padding));
            }
        }
    }
    return 0;
}
